// 闭包是指有权访问另一个函数作用域中变量的函数，创建闭包的最常见的方式就是在一个函数内创建另一个函数，通过另一个函数访问这个函数的局部变量。
// 闭包的特性：
// 1. 闭包可以访问外部函数的变量
// 2. 闭包的变量会常驻在内存中，不会被垃圾回收机制回收
// 3. 闭包可以实现封装和私有变量的效果

// 举个例子：
function outer() {
  var name = 'John';
  function inner() {
    console.log(name);
  }
  return inner;
}
var innerFn = outer();
innerFn(); // 输出 'John'

// 在这个例子中，inner函数可以访问outer函数中的变量name，因为inner函数是在outer函数中定义的，所以它可以访问outer函数中的所有变量和参数。
//当outer函数执行完毕后，inner函数仍然可以访问outer函数中的变量name，
//这是因为inner函数形成了一个闭包，它可以访问outer函数中的所有变量和参数，并且这些变量和参数不会被垃圾回收机制回收，
//因为inner函数仍然在使用它们。

// 闭包的应用：
// 1. 实现模块化
// 2. 实现私有变量和方法
// 3. 实现缓存
// 4. 实现柯里化

// 柯里化函数是指将一个接受多个参数的函数转化为接受单一参数的函数，并且返回接受余下参数且返回结果的新函数的技术。
// 举个例子：
function add(a, b, c) {
  return a + b + c;
}
function curry(fn) {
  var args = [];
  return function() {
    if (arguments.length === 0) {
      return fn.apply(this, args);
    } else {
      Array.prototype.push.apply(args, arguments);
      return arguments.callee;
    }
  }
}
var addCurry = curry(add);
addCurry(1)(2)(3)(); // 输出 6

